package com.taoge.autoconfig;

import com.taoge.aop.SlideWindowLimitAspect;
import com.taoge.properties.RateLimitProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * Redis滑动时间窗口限流自动装配配置类
 * @author Mr.Tao
 */
@ConditionalOnExpression("#{'true'.equals(environment['rate-limit.enabled']) and ('3'.equals(environment['rate-limit.type']) or '-1'.equals(environment['rate-limit.type']))}")
@Import({RateLimitProperties.class})
@Configuration
@Slf4j
public class SlideWindowLimitAutoConfig {

    @Autowired
    private RateLimitProperties limitProperties;

    @Autowired
    @Qualifier("limitRedisTemplate")
    private RedisTemplate<String, Long> redisTemplate;

    @Bean(name = "slideWindowLimitPointCut")
    public Pointcut slideWindowLimitPointCut() {
        return limitProperties.getPointcutExpression(limitProperties.getStrategyConfig().getSlideWindowLimitPackagePath());
    }

    @Bean(name = "slideWindowLimitAspect")
    public SlideWindowLimitAspect slideWindowLimitAspect() {
        return new SlideWindowLimitAspect(redisTemplate, limitProperties);
    }

    /**
     * 自定义切面，可以灵活配置切点和切面。
     * @return 切面
     */
    @Bean(name = "slideWindowLimitDefaultPointcutAdvisor")
    public DefaultPointcutAdvisor slideWindowLimitDefaultPointcutAdvisor() {
        DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor();
        defaultPointcutAdvisor.setPointcut(slideWindowLimitPointCut());
        defaultPointcutAdvisor.setAdvice(slideWindowLimitAspect());
        log.info("基于Redis的滑动时间窗口限流配置加载成功，限流接口所在包路径为" + limitProperties.getLimitPath(limitProperties.getStrategyConfig().getSlideWindowLimitPackagePath()));
        return defaultPointcutAdvisor;
    }

}
